#include "networkmanager.h"
#include "MessageType.h"
#include "cryptutils.h"
#include <QDataStream>
#include <QTimerEvent>
#include <QDebug>
#include <QMessageBox>


NetworkManager::NetworkManager(QObject *parent)
    : QTcpSocket(parent)
    , reconnectTimer(new QTimer(this))
    , connectedFlag(false)
    , expectedDataSize(0)
{
    setupNetwork();
}

NetworkManager::~NetworkManager()
{
    // 析构函数
}

void NetworkManager::setupNetwork()
{
    // 连接信号槽
    connect(this, &QTcpSocket::connected, this, &NetworkManager::onConnected);
    connect(this, &QTcpSocket::disconnected, this, &NetworkManager::onDisconnected);
    connect(this, &QTcpSocket::readyRead, this, &NetworkManager::onReadyRead);
    connect(this, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error),
            this, &NetworkManager::onErrorOccurred);
    
    // 设置重连定时器
    connect(reconnectTimer, &QTimer::timeout, this, &NetworkManager::onReconnectTimeout);
    reconnectTimer->setInterval(5000); // 5秒重连一次
}

bool NetworkManager::connectToServer(const QString& host, quint16 port)
{
    // 实现连接到服务器功能
    
    // 停止重连定时器
    if (reconnectTimer->isActive()) {
        reconnectTimer->stop();
    }
    
    // 连接到服务器
    this->connectToHost(host, port);
    
    // 等待连接结果
    if (this->waitForConnected(3000)) { // 等待3秒
        // QTcpSocket会在连接成功时自动发出connected信号
        // onConnected槽函数会设置connectedFlag为true
        return true;
    } else {
        connectedFlag = false;
        currentError = this->errorString();
        emit networkError(currentError);
        return false;
    }
}

void NetworkManager::sendRegisterRequest(const QString& username, const QString& password)
{
    // 实现发送注册请求功能，使用TLV格式打包数据
    // 保存用户名和密码，用于后续步骤
    pendingUsername = username;
    pendingPassword = password;
    
    // 发送用户名进行注册第一步
    QByteArray userData = username.toUtf8();
    sendTLV(TASK_SIGNUP_SECTION1, userData.length(), userData);
}

void NetworkManager::disconnectFromServer()
{
    // 实现断开连接功能
    
    if (this->state() == QAbstractSocket::ConnectedState) {
        this->disconnectFromHost();
        // QTcpSocket会在断开连接时自动发出disconnected信号
        // onDisconnected槽函数会设置connectedFlag为false
    }
}

void NetworkManager::sendLoginRequest(const QString& username, const QString& password)
{
    // 实现发送登录请求功能，使用TLV格式打包数据
    // 保存用户名和密码，用于后续步骤
    pendingUsername = username;
    pendingPassword = password;
    
    // 发送用户名进行登录第一步
    QByteArray userData = username.toUtf8();
    sendTLV(TASK_LOGIN_SECTION1, userData.length(), userData);
}

bool NetworkManager::isConnected() const
{
    return connectedFlag;
}

QString NetworkManager::getError() const
{
    return currentError;
}

void NetworkManager::onConnected()
{
    connectedFlag = true;
    // QTcpSocket的connected信号已经发出，无需再手动发出
    // 直接设置连接标志即可
}

void NetworkManager::onDisconnected()
{
    connectedFlag = false;
    
    // 启动重连定时器
    if (!reconnectTimer->isActive()) {
        reconnectTimer->start();
    }
}

void NetworkManager::onReadyRead()
{
    // 实现接收数据处理功能，解析TLV格式数据
    while (this->bytesAvailable() > 0) {
        if (expectedDataSize == 0) {
            // 如果期待数据为0，说明还没开始读取长度信息
            if (this->bytesAvailable() < static_cast<qint64>(sizeof(int) * 2)) {
                // 数据不完整，等待下次数据到达
                return;
            }
            
            // 读取类型和长度
            this->read(reinterpret_cast<char*>(&currentPacket._type), sizeof(int));
            this->read(reinterpret_cast<char*>(&currentPacket._length), sizeof(int));
            
            expectedDataSize = currentPacket._length;
            
            // 验证数据长度是否合理
            if (expectedDataSize < 0 || expectedDataSize > 10240) {  // 增加到10KB
                // 处理错误：无效的数据长度
                currentError = "Invalid data length";
                emit networkError(currentError);
                this->abort();//立即强制断开连接
                return;
            }
        }
        
        // 检查是否有足够的数据体
        if (this->bytesAvailable() < expectedDataSize) {
            // 数据体不完整，等待下次数据到达
            return;
        }
        
        // 读取完整的数据体
        QByteArray msgData = this->read(expectedDataSize);
        currentPacket._msg = msgData;
        
        // 处理接收到的数据包
        handleReceivedPacket(currentPacket);
        
        // 重置状态，准备处理下一个消息
        expectedDataSize = 0;
        currentPacket.clear();
    }
}

void NetworkManager::onErrorOccurred(QAbstractSocket::SocketError socketError)
{
    // 实现错误处理功能
    Q_UNUSED(socketError);
    currentError = this->errorString();
    emit networkError(currentError);
    
    // 启动重连定时器
    if (!reconnectTimer->isActive()) {
        reconnectTimer->start();
    }
}

void NetworkManager::onReconnectTimeout()
{
    // 实现重连功能
    // 尝试重新连接到服务器
    // 这里使用默认的服务器地址和端口，实际项目中应该保存用户上次连接的地址
    connectToServer("192.168.105.108", 8000);
}

void NetworkManager::sendTLV(TaskType type, int len, const QByteArray &msg)
{
    if (!isOpen() || !isWritable()) {
        qWarning() << "TcpSocket is not connected";
        return;
    }
    if (msg.isEmpty()) {
        qWarning() << "UserName or password is empty";
        return;
    }
    
    QByteArray tlv;
    // 将4字节type写入tlv中
    tlv.append(reinterpret_cast<const char *>(&type), sizeof(int));
    // 将4字节len写入tlv中
    tlv.append(reinterpret_cast<const char *>(&len), sizeof(int));
    // 将QString转为Utf-8编码的字节数组，写入tlv中
    qDebug() << msg.toHex();
    tlv.append(msg);
    
    // 发送tlv
    sendn(tlv, sizeof(int) * 2 + len);
    flush();
}


int NetworkManager::sendn(QByteArray buf, int len)
{
    int left = len;
    const char *pCurr = buf.constData();
    while (left > 0) {
        int ret = write(pCurr, len);
        if (ret == -1) {
            qCritical() << "Tcp write failed";
            return len - left;
        }
        pCurr += ret;
        left -= ret;
    }
    return len;
}


/*
void NetworkManager::handleLoginResponse(bool success, const QString& message)
{
    // 实现登录响应处理
    if (success) {
        // 登录成功
        // 可以在这里添加其他成功时的处理逻辑
    } else {
        // 登录失败
        // 可以在这里添加其他失败时的处理逻辑
    }
    
    // 发出登录响应信号
    emit loginResponse(success, message);
}
*/


void NetworkManager::handleReceivedPacket(const Packet& packet)
{
    // 处理接收到的数据包
    switch (packet._type) {
    case TASK_LOGIN_SECTION1_RESP_OK:
        // 用户存在，服务器返回盐值，需要发送加密后的密码
        {
            // 使用盐值生成加密密码并发送
            QString encryptedPassword = CryptUtils::generateEncryptedMessage(pendingUsername, packet._msg);
            QByteArray passwordData = encryptedPassword.toUtf8();
            sendTLV(TASK_LOGIN_SECTION2, passwordData.length(), passwordData);
        }
        break;
    case TASK_LOGIN_SECTION1_RESP_ERROR:
        // 用户不存在
        emit loginResponse(false, "User not found");
        break;
    case TASK_LOGIN_SECTION2_RESP_OK:
        // 登录成功
        qDebug() << "Login successful, device list data size:" << packet._msg.size();
        emit loginResponse(true, "Login successful");

        if(!packet._msg.isEmpty()){
            qDebug() << "Device list data received:" << packet._msg;
            emit deviceListReceived(packet._msg);
        }

        break;
    case TASK_LOGIN_SECTION2_RESP_ERROR:
        // 密码错误
        emit loginResponse(false, "Incorrect password");
        break;
    case TASK_SIGNUP_SECTION1_RESP_OK:
        // 用户名可用，服务器返回盐值，需要发送加密后的密码
        {
            // 使用盐值生成加密密码并发送
            QString encryptedPassword = CryptUtils::generateEncryptedMessage(pendingPassword, packet._msg);
            QByteArray passwordData = encryptedPassword.toUtf8();
            sendTLV(TASK_SIGNUP_SECTION2, passwordData.length(), passwordData);
        }
        break;
    case TASK_SIGNUP_SECTION1_RESP_ERROR:
        // 用户名已存在
        emit registerResponse(false, "Username already exists");
        break;
    case TASK_SIGNUP_SECTION2_RESP_OK:
        // 注册成功
        emit registerResponse(true, "Registration successful");
        break;
    case TASK_SIGNUP_SECTION2_RESP_ERROR:
        // 注册失败
        emit registerResponse(false, "Registration failed");
        break;
    case TASK_PTZ_CONTROL_RESP_ERROR:
        if(count == 0){
            QMessageBox::warning(nullptr , "提示" , "请选中其中一个窗口");
            ++count;
        }else{
            count = 0;
        }

        break;
    case TASK_STM32_SENSORS:
        emit Record_STM32_info(QString::fromUtf8(packet._msg));


    default:
        // 未知类型
        qDebug() << "Unknown packet type:" << packet._type;

        break;
    }
}
